﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core;

namespace COFE.Core.Profile
{
    /// <summary>
    /// Allow register and access all properties types (FileSystemInfoProperties, etc).
    /// </summary>
    public interface IPropertyDictionary
    {
        /// <summary>
        /// Register all properties in an enumeration.
        /// </summary>        
        void RegisterProperties<T>();

        /// <summary>
        /// Register one property
        /// </summary>        
        void RegisterProperty(object property);

        object[] Properties { get; }

        /// <summary>
        /// Lookup a property from it's property string.
        /// </summary>
        /// <param name="propertyString"></param>
        /// <returns></returns>
        object GetProperty(string propertyString);

        /// <summary>
        /// Lookup a property from it's property id.
        /// </summary>
        /// <param name="propertyString"></param>
        /// <returns></returns>
        object GetProperty(int propId);

        /// <summary>
        /// Use a property string to find a property.
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        string GetPropertyString(object property);

        /// <summary>
        /// Return a list of property with default value.
        /// </summary>
        /// <returns></returns>
        List<object> GetPropertiesWithDefaultValue();

        /// <summary>
        /// Return whether a property exists in the dictionary.
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        bool HasProperty(object property);

        bool HasProperty(string propertyString);

        /// <summary>
        /// Return whether the property has default value (settable by ValueTypeAttribute)
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        bool HasDefaultValue(object property);

        /// <summary>
        /// Get the default value of the property.
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        object GetDefaultValue(object property);
    }

    public static class IPropertyDictionaryExtension
    {
        public static List<string> GetPropertiesStringWithDefaultValue(this IPropertyDictionary propDic)
        {
            return (from prop in propDic.GetPropertiesWithDefaultValue()
                    select propDic.GetPropertyString(prop)).ToList();
        }


        public static bool HasProperty(this IPropertyDictionary propDic, string propertyString)
        {
            object property = propDic.GetProperty(propertyString);
            if (property != null)
                return propDic.HasProperty(property);
            else throw new KeyNotFoundException(propertyString);
        }

        public static bool HasDefaultValue(this IPropertyDictionary propDic, string propertyString)
        {
            object property = propDic.GetProperty(propertyString);
            if (property != null)
                return propDic.HasDefaultValue(property);
            else throw new KeyNotFoundException(propertyString);
        }

        public static object GetDefaultValue(this IPropertyDictionary propDic, string propertyString)
        {
            object property = propDic.GetProperty(propertyString);
            if (property != null)
                return propDic.GetDefaultValue(property);
            else throw new KeyNotFoundException(propertyString);
        }

        public static PropertyPair GetDefaultValuePP(this IPropertyDictionary propDic, object property)
        {
            if (propDic.HasDefaultValue(property))
            {
                object defValue = propDic.GetDefaultValue(property);
                return new PropertyPair(property, defValue);
            }
            throw new NotSupportedException();
        }

        public static PropertyPair GetDefaultValuePP(this IPropertyDictionary propDic, string propertyString)
        {
            object property = propDic.GetProperty(propertyString);
            return propDic.GetDefaultValuePP(property);            
        }
    }
}
